package com.linln.admin.app.controller;

import com.linln.admin.app.constants.AppConstants;
import com.linln.admin.app.domain.AppInfo;
import com.linln.admin.app.domain.AppVersion;
import com.linln.admin.app.service.ProductionLineService;
import com.linln.admin.app.service.VersionService;
import com.linln.admin.app.validator.VersionValid;
import com.linln.common.enums.StatusEnum;
import com.linln.common.utils.EntityBeanUtil;
import com.linln.common.utils.ResultVoUtil;
import com.linln.common.utils.StatusUtil;
import com.linln.common.vo.ResultVo;
import com.linln.component.actionLog.action.SaveAction;
import com.linln.component.actionLog.action.StatusAction;
import com.linln.component.actionLog.annotation.ActionLog;
import com.linln.component.actionLog.annotation.EntityParam;
import com.linln.modules.system.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.ExampleMatcher;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Map;

/**
 * @author 陶富成
 * @date 2021/07/09
 */
@Controller
@RequestMapping("/app/version")
@Slf4j
public class VersionController {

    @Autowired
    private VersionService versionService;
    @Autowired
    private UserService userService;
    @Autowired
    private ProductionLineService productionLineService;

    /**
     * 列表页面
     */
    @GetMapping("/index")
    @RequiresPermissions("app:version:index")
    public String index(Model model, AppVersion appVersion) {

        // 创建匹配器，进行动态查询匹配
        ExampleMatcher matcher = ExampleMatcher.matching()
                .withMatcher("version", match -> match.contains())
                .withMatcher("demand_title", match -> match.contains())
                .withMatcher("demand_url", match -> match.contains());

        // 获取数据列表
        Example<AppVersion> example = Example.of(appVersion, matcher);
        Page<AppVersion> list = versionService.getPageList(example);

        // 封装数据
        model.addAttribute("list", list.getContent());
        model.addAttribute("page", list);
        model.addAttribute("users", userService.getAll());
        model.addAttribute("prodLines", productionLineService.getAll());
        return "/app/version/index";
    }

    /**
     * 跳转到添加页面
     */
    @GetMapping("/add")
    @RequiresPermissions("app:version:add")
    public String toAdd(Model model) {
        model.addAttribute("users", userService.getAllUseful());
        return "/app/version/add";
    }

    /**
     * 跳转到编辑页面
     */
    @GetMapping("/edit/{id}")
    @RequiresPermissions("app:version:edit")
    public String toEdit(@PathVariable("id") AppVersion appVersion, Model model) {
        model.addAttribute("appVersion", appVersion);
        model.addAttribute("users", userService.getAllUseful());
        model.addAttribute("memberIds", versionService.getUserIdsByVersionId(appVersion.getId()));
        return "/app/version/add";
    }

    /**
     * 保存添加/修改的数据
     *
     * @param valid 验证对象
     */
    @PostMapping("/save")
    @RequiresPermissions({"app:version:add", "app:version:edit"})
    @ResponseBody
    @ActionLog(name = "版本信息管理", message = "版本：${version}", action = SaveAction.class)
    public ResultVo save(@Validated VersionValid valid, @EntityParam AppVersion appVersion, String[] memberIds) {
        appVersion.setVersion(appVersion.getVersion().trim().toLowerCase());
        appVersion.setHotfix_flag(StringUtils.defaultIfBlank(appVersion.getHotfix_flag(), AppConstants.NO));
        // 复制保留无需修改的数据
        if (appVersion.getId() != null) {
            AppVersion beAppVersion = versionService.getById(appVersion.getId());
            EntityBeanUtil.copyProperties(beAppVersion, appVersion);
        }

        // 保存数据
        versionService.save(appVersion, memberIds);
        return ResultVoUtil.SAVE_SUCCESS;
    }

    /**
     * 跳转到详细页面
     */
    @GetMapping("/detail/{id}")
    @RequiresPermissions("app:version:detail")
    public String toDetail(@PathVariable("id") String versionId, Model model) {
        if (!StringUtils.isNumeric(versionId)) {
            return "redirect:/404";
        }
        AppVersion appVersion = versionService.getById(Long.parseLong(versionId));
        model.addAttribute("appVersion", appVersion);
        model.addAttribute("users", userService.getAll());
        model.addAttribute("hasConflict", versionService.hasConflict(appVersion.getId()));
        model.addAttribute("canReopen", versionService.canReopen(appVersion.getId()));
        model.addAttribute("memberIds", versionService.getUserIdsByVersionId(appVersion.getId()));
        return "/app/version/detail";
    }

    /**
     * 检查共用的一些应用情况
     *
     * @param model
     * @return
     */
    @GetMapping("/check/appcurrency")
    @RequiresPermissions("app:version:check:appcurrency")
    public String checkCurrency(Model model) {
        Map<AppInfo, List<AppVersion>> apps = versionService.combineAppCurrencyInfo();
        model.addAttribute("apps", apps);
        model.addAttribute("users", userService.getAll());
        return "/app/version/app_currency";
    }

    /**
     * 检查指定每个版本中的应用是否存在合并后的冲突
     */
    @GetMapping("/merge/result")
    @ResponseBody
    public ResultVo mergeResult(String versionId) {
        try {
            return ResultVoUtil.success("成功", versionService.hasConflict(Long.parseLong(versionId)));
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return ResultVoUtil.error("获取失败！" + e.getMessage());
        }
    }

    /**
     * 设置一条或者多条数据的状态
     */
    @RequestMapping("/status/{param}")
    @RequiresPermissions("app:version:status")
    @ResponseBody
    @ActionLog(name = "版本状态", action = StatusAction.class)
    public ResultVo status(
            @PathVariable("param") String param,
            @RequestParam(value = "ids", required = false) List<Long> ids) {
        // 更新状态
        StatusEnum statusEnum = StatusUtil.getStatusEnum(param);
        if (versionService.updateStatus(statusEnum, ids)) {
            return ResultVoUtil.success(statusEnum.getMessage() + "成功");
        } else {
            return ResultVoUtil.error(statusEnum.getMessage() + "失败，请重新操作");
        }
    }

    /**
     * 将项目进行废弃操作
     *
     * @param ids
     * @return
     */
    @RequestMapping("/discard")
    @RequiresPermissions("app:version:status")
    @ResponseBody
    @ActionLog(name = "版本分支管理", message = "将以下版本废弃：${ids}")
    public ResultVo discard(
            @RequestParam(value = "ids", required = false) List<Long> ids) {
        if (versionService.discard(ids)) {
            return ResultVoUtil.success("操作成功");
        } else {
            return ResultVoUtil.error("操作失败，请重新操作");
        }
    }

    //===================下面是代码库相关的操作===================

    /**
     * 手动触发新建发布分支
     *
     * @param versionId
     * @return
     */
    @RequestMapping("/branch/newrelease")
    @RequiresPermissions({"app:version:branch:newrelease"})
    @ResponseBody
    @ActionLog(name = "版本分支管理", message = "给版本[${versionId}]创建发布分支")
    public ResultVo createReleaseBranch(String versionId) {
        try {
            Long taskId = versionService.createReleaseBranch(Long.parseLong(versionId));
            //新建了发布分支，就同时进行代码规范的校验
            versionService.branchPmdCheck(Long.parseLong(versionId));
            return ResultVoUtil.success("创建成功，请等待创建结果！", taskId);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return ResultVoUtil.error(e.getMessage());
        }
    }

    /**
     * 发布前代码规范检测
     *
     * @param versionId
     * @return
     */
    @RequestMapping("/branch/pmdcheck")
    @RequiresPermissions({"app:version:branch:pmdcheck"})
    @ResponseBody
    public ResultVo branchPmdCheck(String versionId) {
        try {
            return ResultVoUtil.success("任务创建成功，请等待检查结果！", versionService.branchPmdCheck(Long.parseLong(versionId)));
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return ResultVoUtil.error(e.getMessage());
        }
    }

    /**
     * 手动设置为已发布
     *
     * @param versionId
     * @return
     */
    @RequestMapping("/published")
    @RequiresPermissions({"app:version:published"})
    @ResponseBody
    @ActionLog(name = "版本分支管理", message = "将版本[${versionId}]设置为已上线状态")
    public ResultVo manualPublished(String versionId) {
        try {
            return ResultVoUtil.success("处理成功！", versionService.doPublished(Long.parseLong(versionId)));
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return ResultVoUtil.error(e.getMessage());
        }
    }

    /**
     * 重开已经发布的项目，主要是在项目上线后，在线验收发现问题并且没有新的上线，可以重开发布
     *
     * @param versionId
     * @return
     */
    @RequestMapping("/reopen")
    @RequiresPermissions({"app:version:reopen"})
    @ResponseBody
    @ActionLog(name = "版本分支管理", message = "将已上线的版本[${versionId}]重新打开")
    public ResultVo reopen(String versionId) {
        try {
            versionService.reopen(Long.parseLong(versionId));
            return ResultVoUtil.success("处理成功！");
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return ResultVoUtil.error(e.getMessage());
        }
    }


    //=================================下面是发布材料相关操作===============
    @GetMapping("/branch/combinepub")
    @RequiresPermissions({"app:version:branch:combinepub"})
    public String combinePublishProfiles(String versionId, Model model) {
        model.addAttribute("versionId", versionId);
        return "/app/version/combinepub";
    }

    /**
     * 获取汇总的资料
     *
     * @param versionId
     * @return
     */
    @PostMapping("/branch/combinepub")
    @RequiresPermissions({"app:version:branch:combinepub"})
    @ResponseBody
    public ResultVo combinePublishProfiles(String versionId, String combinePubEnv, String combinePubProfile) {
        try {
            return ResultVoUtil.success("操作成功！", versionService.combinePublishProfiles(Long.parseLong(versionId), combinePubEnv, combinePubProfile));
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return ResultVoUtil.error(e.getMessage());
        }
    }
}